import 'dart:io';

import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart';
import 'package:flutter_bmflocation/flutter_bmflocation.dart';
import 'package:hygf/util/LoadingUtils.dart';
import 'package:permission_handler/permission_handler.dart';

import '../HDSysUtils.dart';
import 'hap_location.dart';
import 'loc_task.dart';

/// 定位管理器
///
/// 单例模式
///
/// Created by LY on 2022.7.8
class LocationManager {
  LocationManager._internal();

  static late final LocationManager _instance = LocationManager._internal();
  late final LocationFlutterPlugin _myLocPlugin = LocationFlutterPlugin();

  factory LocationManager() => _instance;

  bool isStart = false;

  final Map<String, LocTask> _tasks = {};

  HapLocation? _lastLocation;

  /// 开启定位
  ///
  /// 调用_startLocation方法即表示同意隐私政策 所以请在调用前请用户签署同意隐私政策


  Future<bool> _startLocation() async {
    bool hasPermission = await requestLocationPermission();
    if (!hasPermission) {
      return false;
    }
    _myLocPlugin.setAgreePrivacy(true);
    // if (!result) {
    //   return false;
    // }
    // 添加定位回调
    _myLocPlugin.seriesLocationCallback(callback: (BaiduLocation result) {
      double? radius;
      // 如果是android 就使用精度
      // 如果是iOS 就使用水平精度
      if (Platform.isAndroid) {
        radius = result.radius;
      } else if (Platform.isIOS) {
        radius = result.horizontalAccuracy;
      }

      _lastLocation = HapLocation(
          radius: radius,
          longitude: result.longitude.toString(),
          latitude: result.latitude.toString(),
          address: result.address,
          locationDetail: result.locationDetail);
      // 获取当前时间 如果任务的nextTime比当前时间早 就调用回调函数
      int time = DateTime.now().millisecondsSinceEpoch;
      _tasks.forEach((key, value) {
        if (time >= value.nextTime) {
          value.callback(key, _lastLocation!);
          value.nextTime = time + (value.period * 1000);
        }
      });
    });

    Map iosMap = _initIOSOptions().getMap();
    Map androidMap = _initAndroidOptions().getMap();

    bool suc = await _myLocPlugin.prepareLoc(androidMap, iosMap);
    if (!suc) {
      return false;
    }
    isStart = await _myLocPlugin.startLocation();
    return isStart;
  }

  Future<bool> _stopLocation() async {
    isStart = !await _myLocPlugin.stopLocation();
    return isStart;
  }

  BaiduLocationAndroidOption _initAndroidOptions() {
    BaiduLocationAndroidOption options = BaiduLocationAndroidOption(
        // 定位模式，可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        locationMode: BMFLocationMode.hightAccuracy,
        // 是否需要返回地址信息
        isNeedAddress: true,
        // 是否需要返回海拔高度信息
        isNeedAltitude: true,
        // 是否需要返回周边poi信息
        isNeedLocationPoiList: true,
        // 是否需要返回新版本rgc信息
        isNeedNewVersionRgc: true,
        // 是否需要返回位置描述信息
        isNeedLocationDescribe: true,
        // 是否使用gps
        openGps: true,
        // 可选，设置场景定位参数，包括签到场景、运动场景、出行场景
        locationPurpose: BMFLocationPurpose.signIn,
        // 坐标系
        coordType: BMFLocationCoordType.gcj02,
        // 设置发起定位请求的间隔，int类型，单位ms
        // 如果设置为0，则代表单次定位，即仅定位一次，默认为0
        scanspan: 3 * 1000);
    return options;
  }

  /// 设置iOS option 但是暂时不考虑iOS端 故该参数暂时无效
  BaiduLocationIOSOption _initIOSOptions() {
    BaiduLocationIOSOption options = BaiduLocationIOSOption(
      // 坐标系
      coordType: BMFLocationCoordType.bd09ll,
      // 位置获取超时时间
      locationTimeout: 10,
      // 获取地址信息超时时间
      reGeocodeTimeout: 10,
      // 应用位置类型 默认为automotiveNavigation
      activityType: BMFActivityType.automotiveNavigation,
      // 设置预期精度参数 默认为best
      desiredAccuracy: BMFDesiredAccuracy.best,
      // 是否需要最新版本rgc数据
      isNeedNewVersionRgc: true,
      // 指定定位是否会被系统自动暂停
      pausesLocationUpdatesAutomatically: false,
      // 指定是否允许后台定位,
      // 允许的话是可以进行后台定位的，但需要项目配置允许后台定位，否则会报错，具体参考开发文档
      allowsBackgroundLocationUpdates: true,
      // 设定定位的最小更新距离
      distanceFilter: 10,
    );
    return options;
  }

  /// 获取缓存中的最近一次的位置 用于加速界面展示速度
  /// 注意：该方法获取到的有可能为null
  HapLocation? getLastLocation() {
    return _lastLocation;
  }

  /// 获取当前位置-单次定位
  getNow(Function(HapLocation location) callback) {
    addTask(10, (id, location) {
      callback(location);
      removeTask(id);
    });
  }

  /// 添加定位任务-连续定位
  ///
  /// 如果没有开启连续定位功能 会自动开启
  /// [period] 频次 单位为秒
  String addTask(int period, Function(String id, HapLocation location) callback) {
    String uuid = HDSysUtils.generateReadableUUID();
    var task = LocTask(period, callback);
    _tasks[uuid] = task;
    if (!isStart) {
      _startLocation();
    }
    return uuid;
  }

  /// 通过添加任务时返回的 [id] 移除任务 如果移除完成后任务列表为空 就会结束连续定位功能
  removeTask(String id) {
    _tasks.remove(id);
    if (_tasks.isEmpty) {
      _stopLocation();
    }
  }

  /// 清空定位任务列表并结束连续定位功能
  clearTask() {
    _tasks.clear();
    _stopLocation();
  }

  /// 申请定位权限
  /// 授予定位权限返回true， 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      //已经授权
      return true;
    } else {
      //未授权则发起一次申请
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }

  getLocation() async {
    bool hasPermission = await requestLocationPermission();
    if (!hasPermission) {
      LoadingUtils.showToast("未获取定位权限");
      return;
    }
  }
}
